﻿using Dexter.CallContext;
using Dexter.Dependency;
using Dexter.Logger.Contracts;
using Dexter.Scheduler.Quartz.Extensions;
using Quartz.Spi;

namespace Dexter.Scheduler.Quartz.Factory {
	/// <summary>
	/// The implementation of <see cref="IJobFactory"/> for Quartz.Net job factory.
	/// </summary>
	public class DexterJobFactory : IJobFactory {
		readonly IDexterContainer container;

		/// <summary>
		/// Initializes a new instance of the <see cref="DexterJobFactory"/> class.
		/// </summary>
		/// <param name="container">The container.</param>
		public DexterJobFactory ( IDexterContainer container ) {
			this.container = container;
		}

		/// <summary>
		/// Called by the scheduler at the time of the trigger firing, in order to
		///             produce a <see cref="T:Quartz.IJob"/> instance on which to call Execute.
		/// </summary>
		/// <remarks>
		/// <p>It should be extremely rare for this method to throw an exception -
		///             basically only the the case where there is no way at all to instantiate
		///             and prepare the Job for execution.  When the exception is thrown, the
		///             Scheduler will move all triggers associated with the Job into the
		///             <see cref="F:Quartz.TriggerState.Error"/> state, which will require human
		///             intervention (e.g. an application restart after fixing whatever 
		///             configuration problem led to the issue wih instantiating the Job. 
		///             </p>
		/// </remarks>
		/// <param name="bundle">The TriggerFiredBundle from which the <see cref="T:Quartz.JobDetail"/>
		///             and other info relating to the trigger firing can be obtained.
		///             </param><throws>SchedulerException if there is a problem instantiating the Job. </throws>
		/// <returns>
		/// the newly instantiated Job
		/// </returns>
		public global::Quartz.IJob NewJob ( TriggerFiredBundle bundle ) {
			var newJob = container.Resolve<IJob> ( bundle.JobDetail.GetContainerJobName() );
			return new QuartzJobWrapper ( newJob , container.Resolve <IDexterCall> ( ) , container.Resolve <ILogger> ( ) );
		}
	}
}
